package com.sghd.candy.module.account.manager;

import com.sghd.candy.utils.DateHelper;
import com.sghd.common.ramcache.IEntity;
import com.sghd.common.ramcache.anno.Cached;
import com.sghd.common.ramcache.anno.CachedSizes;
import com.sghd.common.ramcache.anno.Persister;
import com.sghd.common.ramcache.anno.Persisters;
import com.sghd.common.ramcache.enhance.Enhance;
import com.sghd.common.utils.time.DateUtils;
import com.sghd.pojo.candy.account.AccountState;

import javax.persistence.*;
import java.util.Date;

/**
 * 账户实体
 */
@Entity
@Table(catalog = "bsdld", uniqueConstraints = {@UniqueConstraint(columnNames = {"uid"})})
@Cached(size = CachedSizes.DEFAULT, persister = @Persister(Persisters.PRE_MINUTE))
@NamedNativeQuery(name = Account.ACCOUNT_BY_UID, query = "select * from bsdld.Account where uid=?", resultClass = Account.class)
@NamedQueries({
        @NamedQuery(name = Account.MAX_ID, query = "select max(t.id) from Account as t where t.id between ? and ?")
})
public class Account implements IEntity<Long> {
    public static final String ACCOUNT_BY_UID = "account_by_uid";
    public static final String MAX_ID = "Account_maxId";
    /** 玩家主键*/
    @Id
    private Long id;
    /** 第三方用户id*/
    @Column(name = "uid", length = 50)
    private String uid;
    /** 创建时间 */
    @Column(nullable = false)
    private Date createdOn;
    /** 状态 */
    @Column(nullable = false)
    private int state;
    /** 最后登录时间 */
    private Date loginOn;
    /** 最后登出时间 */
    private Date logoutOn;
    /** 总在线时间 */
    private long timeByTotal;
    /** 总在线天数(从0开始) */
    private int dayByTotal;
    /** 连续登录天数(从0开始) */
    private int dayByContinuous;
    /** 是否在线状态 */
    private boolean online;
    /** 最后登陆IP */
    private String ip;
    /** 是否是游戏客*/
    private boolean guest;
    /** 当天累计时间 */
    private long timeByDay;
    /** 绑定服务器ID **/
    private int serverId;

    public static Account valueOf(long id, String uid) {
        Account account = new Account();
        account.id = id;
        account.uid = uid;
        account.createdOn = new Date();
        //默认游客
        account.guest = true;
        account.serverId = -1;
        return account;
    }

    /**
     * 登陆数据处理
     */
    @Enhance
    public synchronized void login(Date now, String ip, boolean guest, int serverId) {
        this.ip = ip;
        this.serverId = serverId;
        this.online = true;
        //只能把游客状态往非游客状态进行设置
        if (this.guest && this.guest != guest) {
            this.guest = guest;
        }
        // 首次登入的处理
        if (loginOn == null) {
            loginOn = now;
            timeByDay = 0;
            timeByTotal = 0;
            dayByTotal = 1;
            dayByContinuous = 1;
            return;
        }
        Date lastTime = DateHelper.max(loginOn, logoutOn);
        if (lastTime == null) {
            lastTime = new Date();
        }
        if (DateUtils.isToday(lastTime)) {
            // 同天登陆处理
            loginOn = now;
        } else {
            // 当天首次登陆
            timeByDay = 0;
            dayByTotal++;
            Date yestoday = DateUtils.addHours(now, -24);
            if (DateUtils.isSameDay(yestoday, lastTime)) {
                dayByContinuous++;
            } else {
                dayByContinuous = 1;
            }
            loginOn = now;
        }
    }

    /** 登出数据处理 */
    @Enhance
    public synchronized void logout(Date now) {
        int day = DateUtils.calcIntervalDays(loginOn, now);
        if (day == 0) {
            // 登入与登出在同一天
            long times = now.getTime() - loginOn.getTime();
            timeByDay += times;
            timeByTotal += times;
        } else {
            // 登入与登出不在同一天
            dayByTotal += day;
            dayByContinuous += day;
            timeByTotal += now.getTime() - loginOn.getTime();
            timeByDay += now.getTime() - DateUtils.getFirstTime(now).getTime();
        }
        logoutOn = now;
        online = false;
        serverId = -1;
    }

    /**
     * 获取连续在线天数
     *
     * @return
     */
    public int getContinuousDays() {
        return dayByContinuous
                + DateUtils.calcIntervalDays(loginOn, new Date());
    }

    /**
     * 添加帐号状态
     * @param state
     *            状态
     */
    @Enhance
    void addState(AccountState state) {
        this.state = this.state | state.getValue();
    }

    /**
     * 移除帐号状态
     * @param state
     *            状态
     */
    @Enhance
    void removeState(AccountState state) {
        this.state = this.state ^ state.getValue();
    }

    // 逻辑方法

    /**
     * 检查账号是否存在某种状态
     * @param state
     *            状态
     * @return true标识存在，false标识存在
     */
    public boolean hasState(AccountState state) {
        return (this.state & state.getValue()) == state.getValue() ? true
                : false;
    }


    @Enhance
    public void upgrade() {
        setGuest(false);
    }

    @Override
    public Long getId() {
        return id;
    }

    void setId(Long id) {
        this.id = id;
    }

    public String getUid() {
        return uid;
    }

    void setUid(String uid) {
        this.uid = uid;
    }

    public Date getCreatedOn() {
        return createdOn;
    }

    void setCreatedOn(Date createdOn) {
        this.createdOn = createdOn;
    }

    public int getState() {
        return state;
    }

    void setState(int state) {
        this.state = state;
    }

    public Date getLoginOn() {
        return loginOn;
    }

    void setLoginOn(Date loginOn) {
        this.loginOn = loginOn;
    }

    public Date getLogoutOn() {
        return logoutOn;
    }

    void setLogoutOn(Date logoutOn) {
        this.logoutOn = logoutOn;
    }

    public long getTimeByTotal() {
        return timeByTotal;
    }

    void setTimeByTotal(long timeByTotal) {
        this.timeByTotal = timeByTotal;
    }

    public int getDayByTotal() {
        return dayByTotal;
    }

    void setDayByTotal(int dayByTotal) {
        this.dayByTotal = dayByTotal;
    }

    public int getDayByContinuous() {
        return dayByContinuous;
    }

    void setDayByContinuous(int dayByContinuous) {
        this.dayByContinuous = dayByContinuous;
    }

    public boolean isOnline() {
        return online;
    }

    void setOnline(boolean online) {
        this.online = online;
    }

    public String getIp() {
        return ip;
    }

    public boolean isGuest() {
        return guest;
    }

    public void setGuest(boolean guest) {
        this.guest = guest;
    }

    public long getTimeByDay() {
        return timeByDay;
    }

    public void setTimeByDay(long timeByDay) {
        this.timeByDay = timeByDay;
    }

    void setIp(String ip) {
        this.ip = ip;
    }

}